package com.w.base;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.Data;

import java.util.*;

/**
 * @ClassName Result
 * @Description 接口统一返回对象
 * @Author w²
 * @Date 2020/9/27 0027 10:19
 **/
@Data
public class Result {
    private int code;
    private Object data;
    private String msg;

    public boolean successFlag() {
        return this.code == 200;
    }

    /**
     * 私有无参构造 不允许外部私自新加返回状态
     */
    private Result() {
    }

    /**
     * 带参数构造
     *
     * @param resultCodeEnum 返回结果枚举
     */
    public Result(ResultCodeEnum resultCodeEnum) {
        this.code = resultCodeEnum.getStatus();
        this.msg = resultCodeEnum.getDesc();
    }

    /**
     * 带参数构造
     *
     * @param resultCodeEnum 返回结果编码
     * @param msg            结果描述
     */
    public Result(ResultCodeEnum resultCodeEnum, String msg, Object data) {
        this.code = resultCodeEnum.getStatus();
        this.msg = msg;
        if (null == msg || "".equals(msg)) {
            this.msg = resultCodeEnum.getDesc();
        }
        this.data = data;
    }

    /**
     * 带参数构造
     *
     * @param code 返回结果编码
     * @param msg  返回结果描述
     * @param data 结果描述
     */
    public Result(Integer code, Object data, String msg) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    /**
     * 无数据异常返回（code=500）
     *
     * @param msg 结果描述
     * @return
     */
    public static Result error(String msg) {
        return new Result(ResultCodeEnum.ERROR, msg, null);
    }

    public static Result refresh(String msg) {
        return new Result(ResultCodeEnum.REFRESH, msg, null);
    }

    public static Result error(Object data, String msg) {
        return new Result(ResultCodeEnum.ERROR, msg, data);
    }


    public static Result orderError(String msg) {
        return new Result(ResultCodeEnum.ORDER_ERROR, msg, null);
    }


    /**
     * 默认返回结果
     *
     * @return
     */
    public static Result success(Object data) {
        return new Result(ResultCodeEnum.SUCCESS, null, data);
    }

    /**
     * 有数据成功返回（code=200）
     *
     * @param data 返回数据
     * @param msg  结果描述
     * @return
     */
    public static Result success(Object data, String msg) {
        return new Result(ResultCodeEnum.SUCCESS, msg, data);
    }

    /**
     * 有数据成功返回
     *
     * @param code 返回码
     * @param data 返回数据
     * @param msg  结果描述
     * @return
     */
    public static Result success(Integer code, Object data, String msg) {
        return new Result(ResultCodeEnum.SUCCESS, msg, data);
    }

    /**
     * 无数据成功返回（code=200）
     *
     * @param msg 结果描述
     * @return
     */
    public static Result success(String msg) {
        return new Result(ResultCodeEnum.SUCCESS, msg, null);
    }

    /**
     * 参数验证失败异常返回（code=999）
     *
     * @param msg 提示信息
     * @return
     */
    public static Result validationError(String msg) {
        return new Result(ResultCodeEnum.VALIDATION_ERROR, msg, null);
    }

    /**
     * 操作成功，需要重新登录
     *
     * @param msg 提示信息
     * @return 返回对象
     */
    public static Result successNeedLogin(String msg) {
        return new Result(ResultCodeEnum.SUCCESS_NEED_LOGIN, msg, null);
    }

    /**
     * 安全校验失败
     *
     * @param msg
     * @return
     */
    public static Result safetyCheck(String msg) {
        if (msg == null) {
            return new Result(ResultCodeEnum.SAFETY_CHECK);
        } else {
            return new Result(ResultCodeEnum.SAFETY_CHECK, msg, null);
        }
    }

    /**
     * 多vo对象返回
     *
     * @param msg
     * @param objs
     * @return
     */
    public static Result successOnVo(String msg, Object... objs) {
        Result result = new Result(ResultCodeEnum.SUCCESS, msg, null);
        if (objs != null) {
            Map<String, Object> map = new HashMap<>();
            for (Object obj : objs) {
                map.put(captureName(obj.getClass().getSimpleName()), obj);
            }
            result.setData(map);
        }
        return result;
    }

    /**
     * 多vo合并为1
     *
     * @param msg
     * @param objs
     * @return
     */
    public static Result seccessMoreVo(String msg, Object... objs) {
        Result result = new Result(ResultCodeEnum.SUCCESS, msg, null);
        if (objs != null) {
            Map map = new HashMap<>();
            for (Object obj : objs) {
                Map m = JSON.parseObject(JSON.toJSONString(obj, SerializerFeature.WriteMapNullValue), Map.class);
                map.putAll(m);
            }
            result.setData(map);
        }
        return result;
    }

    /**
     * 多vo合并为1
     *
     * @param objs
     * @return
     */
    public static Result seccessMoreVo(Object... objs) {
        Result result = new Result(ResultCodeEnum.SUCCESS, null, null);
        if (objs != null) {
            Map map = new HashMap<>();
            for (Object obj : objs) {
                Map m = JSON.parseObject(JSON.toJSONString(obj, SerializerFeature.WriteMapNullValue), Map.class);
                map.putAll(m);
            }
            result.setData(map);
        }
        return result;
    }

    /**
     * 多VO对象返回
     *
     * @param objs
     * @return
     */
    public static Result successOnVo(Object... objs) {
        Result result = new Result(ResultCodeEnum.SUCCESS, null, null);
        if (objs != null) {
            Map<String, Object> map = new HashMap<>();
            for (Object obj : objs) {
                map.put(captureName(obj.getClass().getSimpleName()), obj);
            }
            result.setData(map);
        }
        return result;
    }


    /**
     * 首字母小写
     *
     * @param name
     * @return
     */
    private static String captureName(String name) {
        char[] cs = name.toCharArray();
        cs[0] += 32;
        return String.valueOf(cs);
    }


    public static final String[] eliminateFileds(String... fields) {
        if (fields == null) {
            return new String[]{"addTime", "updateTime", "version", "addEmpId", "updateEmpId", "addUserId", "updateUserId", "deleteFlag"};
        }
        String[] strs = new String[8 + fields.length];
        strs[0] = "addTime";
        strs[1] = "updateTime";
        strs[2] = "version";
        strs[3] = "addEmpId";
        strs[4] = "updateEmpId";
        strs[5] = "addUserId";
        strs[6] = "updateUserId";
        strs[7] = "deleteFlag";
        for (int i = 0; i < fields.length; i++) {
            strs[8 + i] = fields[i];
        }
        return strs;
    }


    /**
     * 剔除字段
     *
     * @param fields
     * @return
     */
    public Result eliminate(String... fields) throws Exception {
        if (fields == null || fields.length == 0) {
            return this;
        }
        if (this.data == null) {
            return this;
        }
        String str;
        if (getData() instanceof List) {
            List list = (List) getData();
            for (int i = 0; i < list.size(); i++) {
                Object o = list.get(i);
                Map map;
                if (o instanceof Map) {
                    map = (Map) o;
                } else {
                    str = JSONObject.toJSONString(o, SerializerFeature.WriteMapNullValue, SerializerFeature.DisableCircularReferenceDetect,
                            SerializerFeature.WriteDateUseDateFormat);
                    map = JSONObject.parseObject(str);
                }
                eliminateDigui(map, fields);
                list.set(i, map);
            }

        } else {
            Object o = getData();
            Map map;
            if (o instanceof Map) {
                map = (Map) o;
            } else {
                str = JSONObject.toJSONString(getData(), SerializerFeature.WriteMapNullValue, SerializerFeature.DisableCircularReferenceDetect,
                        SerializerFeature.WriteDateUseDateFormat);
                map = JSONObject.parseObject(str);
            }
            eliminateDigui(map, fields);
            setData(map);
        }


        return this;
    }

    public static final void eliminateDigui(Map map, String[] fileds) {
        for (Object key : map.keySet()) {
            Object value = map.get(key);
            if (value != null && value instanceof Map) {
                eliminateDigui((Map) value, fileds);
            } else if (value != null && value instanceof List) {
                for (Object o : (List) value) {
                    if (o instanceof Map) {
                        eliminateDigui((Map) o, fileds);
                    } else {
                        String str = JSONObject.toJSONString(o, SerializerFeature.WriteMapNullValue, SerializerFeature.DisableCircularReferenceDetect,
                                SerializerFeature.WriteDateUseDateFormat);
                        map = JSONObject.parseObject(str);
                        eliminateDigui(map, fileds);
                    }
                }
            }
        }
        for (String filed : fileds) {
            map.remove(filed);
        }
    }

    /**
     * 保留字段
     *
     * @param fields
     * @return
     */
    public Result retain(String... fields) throws Exception {
        if (fields == null || fields.length == 0) {
            return this;
        }
        if (this.data == null) {
            return this;
        }
        Set<String> set = new HashSet<>(fields.length);
        for (String field : fields) {
            set.add(field);
        }
        Set k = new HashSet();
        if (this.data instanceof List) {
            List<Object> list = (List<Object>) this.data;
            if (list.isEmpty()) {
                return this;
            }
            List<Map> listNew = new ArrayList<>(list.size());
            for (int i = 0; i < list.size(); i++) {
                Object o = list.get(i);
                Map map = BeanToMap.objectToMap(o);
                if (i == 0) {
                    Set keySet = map.keySet();
                    for (Object op : keySet) {
                        if (!set.contains(op)) {
                            k.add(op);
                        }
                    }
                }
                for (Object o1 : k) {
                    map.remove(o1);
                }
                listNew.add(map);
            }
            list.clear();
            list = null;
            this.data = listNew;
        } else if (this.data instanceof PageVo) {
            PageVo pageVo = (PageVo) this.data;
            List<Object> list = (List<Object>) pageVo.getData();
            if (list.isEmpty()) {
                return this;
            }
            List<Map> listNew = new ArrayList<>(list.size());
            for (int i = 0; i < list.size(); i++) {
                Object o = list.get(i);
                Map map;
                if (o instanceof Map) {
                    map = (Map) o;
                } else {
                    map = BeanToMap.objectToMap(o);
                }
                if (i == 0) {
                    Set keySet = map.keySet();
                    for (Object op : keySet) {
                        if (!set.contains(op)) {
                            k.add(op);
                        }
                    }
                }
                for (Object o1 : k) {
                    map.remove(o1);
                }
                listNew.add(map);
            }
            list.clear();
            list = null;
            pageVo.setData(listNew);
            this.data = pageVo;
        } else {
            Map map;
            if (this.data instanceof Map) {
                map = (Map) this.data;
            } else {
                map = BeanToMap.objectToMap(this.data);
            }
            Set keySet = map.keySet();
            for (Object op : keySet) {
                if (!set.contains(op)) {
                    k.add(op);
                }
            }
            for (Object o1 : k) {
                map.remove(o1);
            }
            this.data = map;
        }
        set.clear();
        set = null;
        return this;
    }

}
